<?php

namespace App\Logics;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;


class _TagCacheLogic
{
    // laravel 自带的缓存测试
    // TODO  laravel 只有redis、memcached，但不包括 database才支持 tags

    // TODO
    //  通过缓存key制作缓存标签，生成缓存绑定操作成功
    //  但：制作绑定缓存的时候 makeBang 字段必须在模型中设置
    //   删除的时候，必须是模型中设置的缓存字段

    // laravel 的缓存
    public function cache()
    {
        $tags = ['tag1', 'tag2'];
        Cache::add('name1', 'value2');
        Cache::put('name2', 'value2');

        $this->addTag('tag1', 'name1');
        $this->addTag('tag1', 'name2');
        $this->addTag('tag2', 'name1');
        $this->addTag('tag2', 'name2');

        // 查看缓存
        $name1 = Cache::get('name1');
        $name2 = Cache::get('name2');
        var_dump($name1);

        // 删除 标签
        $this->deleteTag('tag1');

        // 查看缓存
        $name1 = Cache::get('name1');
        $name2 = Cache::get('name2');
        var_dump($name1);
    }


    // 查询数据：一条
    public function find($table, $where)
    {
        $args = compact('table', 'where');
        $key  = $this->makeCacheKey($args);   // 所有参数执行 key
        $info = $this->getCache($key);
        if(!is_null($info)){
            return $info;
        }

        // 执行查询
        $info = DB::table($table)->where($where)->first();
        // 如果查询为空
        $info = is_null($info) ? [] : $info;
        // 保存缓存
        $this->addCache($key, $info);
        // 添加绑定
        $tags = $this->makeBang($table, $where);   // where条件制作绑定
        foreach($tags as $_tag){
            $this->addTag($_tag, $key);
        }

        return $info;
    }

    // 查询列表
    public function lists($table, $where, $field = '*', $page = 1, $rows = 20, $order = 'id ASC')
    {
        // 缓存参数
        $args = compact('where', 'field', 'page', 'rows', 'order');
        $key  = $this->makeCacheKey($args);   // 所有参数执行 key
        $list = $this->getCache($key);
        if(!is_null($list)){
            return $list;
        }

        // 查询
        $list = DB::table($table)->where($where)->forPage($page, $rows)->orderByRaw($order)->get()->toArray();
        // 保存缓存
        $this->addCache($key, $list);
        // 保存为绑定
        $tags = $this->makeBang($table, $where);   // where条件制作绑定
        foreach($tags as $_tag){
            $this->addTag($_tag, $key);
        }

        return $list;
    }


    // 根据thinkphp制作绑定缓存
    public function getCache($key)
    {
        return Cache::get($key);
    }

    // 所有参数制作 key
    public function makeCacheKey(...$params)
    {
        if(count($params) === 0){
            return '';
        }

        return md5(var_export($params, 1));
    }

    // 制作表绑定
    public function makeBang($table, $map = [], $self = '')
    {

        $ds = '_';
        if(empty($map)){
            return $table.$ds.($self ? $self.$ds : '');
        }

        // TODO $field  字段必须在模型中设置
        $bang = [];
        foreach($map as $field => $val){
            $name = $table.$ds.$field.$ds;
            if(is_array($val)){
                foreach($val as $_val){
                    $bang[] = $name.$_val;
                }
            } else{
                $bang[] = $name.$val;
            }
        }

        return $bang;
    }

    // 删除某个tag
    public function deleteTag($tag)
    {
        $tags = is_array($tag) ? $tag : [$tag];
        foreach($tags as $tag){
            $keys = Cache::get($tag);
            if($keys){
                foreach($keys as $key){
                    Cache::forget($key);
                }
            }
        }
    }

    // 添加到 tag
    protected function addTag($tag, $key)
    {
        $keys = Cache::get($tag);
        if($keys){
            $keys[] = $key;
        } else{
            $keys = [$key];
        }
        Cache::put($tag, $keys);
    }

    // 添加缓存
    protected function addCache($key, $value)
    {
        Cache::add($key, $value);
    }


}

